#include "mini_redis/RespParser.h"
#include <charconv>
#include <cstddef>
#include <cstdint>
#include <optional>
#include <string>
#include <sys/types.h>
#include <utility>

namespace mini_redis {

void RespParser::append(std::string_view data)
{
    buffer_.append(data.data(), data.size());
}

std::optional<RespValue> RespParser::tryParseOne()
{
    // 1、准备阶段 检查数据 & 提取协议前缀
    if (buffer_.empty())
        return std::nullopt;

    size_t    pos    = 0;
    char      prefix = buffer_[pos++];
    RespValue out;
    bool      ok = false;

    // 2、按前缀分类型处理
    switch (prefix) {
        case '+':
            //  解析 “简单字符串”
            ok = parseSimple(pos, RespType::kSimpleString, out);
            break;
        case '-':
            // 解析 “错误”
            ok = parseSimple(pos, RespType::kError, out);
            break;
        case ':': {
            // 解析 “整数”
            int64_t v = 0;
            ok        = parseInteger(pos, v);
            if (ok) {
                out.type = RespType::kInteger;
                out.bulk = std::to_string(v);
            }
            break;
        }
        case '$':
            // 解析 “批量字符串”
            ok = parseBulkString(pos, out);
            break;
        case '*':
            //  解析 “数组”
            ok = parseArray(pos, out);
            break;
        default: {
            buffer_.erase(0, pos);    // 移除已读取的无效前缀
            return RespValue{
                RespType::kError, std::string("protocol error"), {}};
        }
    }

    if (!ok)
        return std::nullopt;
    buffer_.erase(0, pos);
    return out;
}

bool RespParser::parseLine(size_t& pos, std::string& out_line)
{
    size_t end = buffer_.find("\r\n", pos);
    if (end == std::string::npos)
        return false;
    // 存如out_line
    out_line.assign(buffer_.data() + pos, end - pos);
    pos = end + 2;
    return true;
}

bool RespParser::parseSimple(size_t& pos, RespType t, RespValue& out)
{
    std::string s;
    if (!parseLine(pos, s))
        return false;
    out.type = t;
    out.bulk = std::move(s);
    return true;
}

bool RespParser::parseInteger(size_t& pos, int64_t& out_value)
{
    std::string line;
    if (!parseLine(pos, line))
        return false;
    auto first = line.data();
    auto last  = line.data() + line.size();

    int64_t v      = 0;
    auto [ptr, ec] = std::from_chars(first, last, v);
    if (ec != std::errc() || ptr != last)
        return false;

    out_value = v;
    return true;
}

bool RespParser::parseBulkString(size_t& pos, RespValue& out)
{
    // 1. 解析批量字符串的长度
    int64_t len = 0;
    if (!parseInteger(pos, len)) {
        return false;
    }

    // 2. 处理 “null 批量字符串”（特殊情况）
    if (len == -1) {
        out.type = RespType::kNull;
        return true;
    }

    // 3. 检查长度合法性（排除无效长度）
    if (len < 0)
        return false;

    // 4. 检查缓冲区数据是否完整（关键验证）
    // $6\r\nfoobar\r\n
    if (buffer_.size() < pos + static_cast<size_t>(len) + 2) {
        return false;
    }

    // 5. 提取批量字符串的内容
    out.type = RespType::kBulkString;
    out.bulk.assign(buffer_.data() + pos, static_cast<size_t>(len));

    // 6. 更新位置到内容末尾，准备检查结尾标记
    pos += static_cast<size_t>(len);

    // 7. 验证内容末尾的 \r\n（格式合法性检查）
    if (!(pos + 1 < buffer_.size() && buffer_[pos] == '\r' &&
          buffer_[pos + 1] == '\n')) {
        return false;
    }

    // 8. 跳过结尾的 \r\n，完成解析
    pos += 2;
    return true;
}

bool RespParser::parseArray(size_t& pos, RespValue& out)
{
    // 1、解析数组长度
    int64_t cnt = 0;
    if (!parseInteger(pos, cnt))
        return false;

    // 2. 处理特殊情况：空数组（null array）
    if (cnt == -1) {
        out.type = RespType::kNull;
        return true;
    }

    // 3. 校验数组长度合法性
    if (cnt < 0)
        return false;

    // 4. 初始化数组容器
    out.type = RespType::kArray;
    out.array.clear();
    out.array.reserve(static_cast<size_t>(cnt));

    // 5. 循环解析数组中的每个元素
    for (int64_t i = 0; i < cnt; i++) {
        if (pos >= buffer_.size())
            return false;
        char prefix = buffer_[pos++];
        bool ok     = false;

        RespValue elem;
        switch (prefix) {
            case '+':
                ok = parseSimple(pos, RespType::kSimpleString, elem);
                break;
            case '-':
                ok = parseSimple(pos, RespType::kError, elem);
                break;
            case ':': {
                int64_t v;
                ok = parseInteger(pos, v);
                if (ok) {
                    elem.type = RespType::kInteger;
                    elem.bulk = std::to_string(v);
                }
                break;
            }
            case '$':
                ok = parseBulkString(pos, elem);
                break;
            case '*':
                ok = parseArray(pos, elem);
                break;
            default:
                return false;
        }

        if (!ok)
            return false;

        out.array.emplace_back(elem);
    }

    return true;
}

std::optional<std::pair<RespValue, std::string>>
RespParser::tryParseOneWithRaw()
{
    // 1. 检查缓冲区是否为空
    if (buffer_.empty())
        return std::nullopt;

    // 2. 初始化解析位置和读取前缀
    size_t pos    = 0;
    char   prefix = buffer_[pos++];

    // 3. 声明解析结果变量
    bool      ok = false;
    RespValue out;

    // 4. 根据前缀判断数据类型，调用对应解析函数
    switch (prefix) {
        case '+':
            ok = parseSimple(pos, RespType::kSimpleString, out);
            break;
        case '-':
            ok = parseSimple(pos, RespType::kError, out);
            break;
        case ':': {
            int64_t v = 0;
            ok        = parseInteger(pos, v);
            if (!ok)
                return std::nullopt;
            out.type = RespType::kInteger;
            out.bulk = std::to_string(v);
            break;
        }
        case '$':
            ok = parseBulkString(pos, out);
            break;
        case '*':
            ok = parseArray(pos, out);
            break;
        default: {
            std::string raw(buffer_.data(),
                            pos);    // pos已指向无效前缀的下一位，提取[0, pos)
            buffer_.erase(0, pos);
            return std::make_optional(std::make_pair(
                RespValue{RespType::kError, std::string("protocol error"), {}},
                std::move(raw)));
        }
    }

    // 5. 处理解析失败的情况
    if (!ok)
        return std::nullopt;

    // 6. 提取原始数据并更新缓冲区
    std::string raw;
    raw.assign(buffer_.data(), pos);
    buffer_.erase(0, pos);

    // 7. 返回解析结果
    return std::make_pair(std::move(out), std::move(raw));
}

std::string respSimpleString(std::string_view s)
{
    return "+" + std::string(s) + "\r\n";
}

std::string respError(std::string_view s)
{
    return "-" + std::string(s) + "\r\n";
}

std::string respBulk(std::string_view s)
{
    return "$" + std::to_string(s.size()) + "\r\n" + std::string(s) + "\r\n";
}

std::string respNullBulk()
{
    return "$-1\r\n";
}

std::string respInteger(int64_t v)
{
    return ":" + std::to_string(v) + "\r\n";
}

}    // namespace mini_redis
